<?xml version="1.0" encoding="UTF-8" ?>
<!--

    Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
    under one or more contributor license agreements. See the NOTICE file
    distributed with this work for additional information regarding copyright
    ownership. Camunda licenses this file to you under the Apache License,
    Version 2.0; you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.camunda.bpm.engine.impl.persistence.entity.HistoricJobLogEntity">

  <!-- INSERT -->

  <insert id="insertHistoricJobLogEvent" parameterType="org.camunda.bpm.engine.impl.persistence.entity.HistoricJobLogEventEntity">
    insert into ${prefix}ACT_HI_JOB_LOG (
            ID_,
            TIMESTAMP_,
            JOB_ID_,
            JOB_DUEDATE_,
            JOB_RETRIES_,
            JOB_PRIORITY_,
            JOB_EXCEPTION_MSG_,
            JOB_EXCEPTION_STACK_ID_,
            JOB_STATE_,
            JOB_DEF_ID_,
            JOB_DEF_TYPE_,
            JOB_DEF_CONFIGURATION_,
            ACT_ID_,
            FAILED_ACT_ID_,
            EXECUTION_ID_,
            ROOT_PROC_INST_ID_,
            PROCESS_INSTANCE_ID_,
            PROCESS_DEF_ID_,
            PROCESS_DEF_KEY_,
            DEPLOYMENT_ID_,
            TENANT_ID_,
            HOSTNAME_,
            SEQUENCE_COUNTER_,
            REMOVAL_TIME_
          )
    values (#{id, jdbcType=VARCHAR},
            #{timestamp, jdbcType=TIMESTAMP},
            #{jobId, jdbcType=VARCHAR},
            #{jobDueDate, jdbcType=TIMESTAMP},
            #{jobRetries, jdbcType=INTEGER},
            #{jobPriority, jdbcType=BIGINT},
            #{jobExceptionMessage, jdbcType=VARCHAR},
            #{exceptionByteArrayId, jdbcType=VARCHAR},
            #{state, jdbcType=INTEGER},
            #{jobDefinitionId, jdbcType=VARCHAR},
            #{jobDefinitionType, jdbcType=VARCHAR},
            #{jobDefinitionConfiguration, jdbcType=VARCHAR},
            #{activityId, jdbcType=VARCHAR},
            #{failedActivityId, jdbcType=VARCHAR},
            #{executionId, jdbcType=VARCHAR},
            #{rootProcessInstanceId, jdbcType=VARCHAR},
            #{processInstanceId, jdbcType=VARCHAR},
            #{processDefinitionId, jdbcType=VARCHAR},
            #{processDefinitionKey, jdbcType=VARCHAR},
            #{deploymentId, jdbcType=VARCHAR},
            #{tenantId, jdbcType=VARCHAR},
            #{hostname, jdbcType=VARCHAR},
            #{sequenceCounter, jdbcType=BIGINT},
            #{removalTime, jdbcType=TIMESTAMP}
    )
  </insert>

  <!-- UPDATE -->

  <update id="updateJobLogByRootProcessInstanceId"
          parameterType="java.util.Map">
      update ${prefix}ACT_HI_JOB_LOG set
      REMOVAL_TIME_ = #{removalTime, jdbcType=TIMESTAMP}

      where ROOT_PROC_INST_ID_ = #{rootProcessInstanceId, jdbcType=VARCHAR}
  </update>

  <update id="updateJobLogByRootProcessInstanceId_mssql"
          parameterType="java.util.Map">
      update RES set
      RES.REMOVAL_TIME_ = #{removalTime, jdbcType=TIMESTAMP}
      FROM ${prefix}ACT_HI_JOB_LOG RES WITH (FORCESEEK)
      where RES.ROOT_PROC_INST_ID_ = #{rootProcessInstanceId, jdbcType=VARCHAR}
  </update>

  <update id="updateJobLogByProcessInstanceId"
          parameterType="java.util.Map">
    update ${prefix}ACT_HI_JOB_LOG
      set REMOVAL_TIME_ = #{removalTime, jdbcType=TIMESTAMP}
      where PROCESS_INSTANCE_ID_ = #{processInstanceId, jdbcType=VARCHAR}
  </update>

  <update id="updateJobLogByProcessInstanceId_mssql"
          parameterType="java.util.Map">
    update RES set
      RES.REMOVAL_TIME_ = #{removalTime, jdbcType=TIMESTAMP}
      FROM ${prefix}ACT_HI_JOB_LOG RES WITH (FORCESEEK)
      where RES.PROCESS_INSTANCE_ID_ = #{processInstanceId, jdbcType=VARCHAR}
  </update>

  <update id="updateJobLogByBatchId"
          parameterType="java.util.Map">
      update ${prefix}ACT_HI_JOB_LOG set
      REMOVAL_TIME_ = #{removalTime, jdbcType=TIMESTAMP}

      where JOB_DEF_CONFIGURATION_ = #{batchId, jdbcType=VARCHAR}
  </update>

  <update id="updateJobLogByBatchId_mssql"
          parameterType="java.util.Map">
      update RES set
      RES.REMOVAL_TIME_ = #{removalTime, jdbcType=TIMESTAMP}
      FROM ${prefix}ACT_HI_JOB_LOG RES WITH (FORCESEEK)

      where RES.JOB_DEF_CONFIGURATION_ = #{batchId, jdbcType=VARCHAR}
  </update>

  <!-- DELETE -->

  <delete id="deleteHistoricJobLogById">
    delete from ${prefix}ACT_HI_JOB_LOG where ID_ = #{id}
  </delete>

  <delete id="deleteHistoricJobLogByJobId">
    delete from ${prefix}ACT_HI_JOB_LOG where JOB_ID_ = #{jobId}
  </delete>

  <delete id="deleteHistoricJobLogByProcessInstanceIds">
    delete
    from ${prefix}ACT_HI_JOB_LOG
    where
      <bind name="listOfIds" value="list"/>
      <bind name="fieldName" value="'PROCESS_INSTANCE_ID_'"/>
      <include refid="org.camunda.bpm.engine.impl.persistence.entity.Commons.applyInForPaginatedCollection"/>
  </delete>

  <delete id="deleteHistoricJobLogByProcessDefinitionId">
    delete from ${prefix}ACT_HI_JOB_LOG where PROCESS_DEF_ID_ = #{processDefinitionId}
  </delete>

  <delete id="deleteHistoricJobLogByDeploymentId">
    delete from ${prefix}ACT_HI_JOB_LOG where DEPLOYMENT_ID_ = #{deploymentId}
  </delete>

  <delete id="deleteHistoricJobLogByHandlerType">
    delete from ${prefix}ACT_HI_JOB_LOG where JOB_DEF_TYPE_ = #{handlerType}
  </delete>

  <delete id="deleteHistoricJobLogByJobDefinitionId">
    delete from ${prefix}ACT_HI_JOB_LOG where JOB_DEF_ID_ = #{jobDefinitionId}
  </delete>

  <delete id="deleteHistoricJobLogByBatchIds">
    delete from ${prefix}ACT_HI_JOB_LOG
    where
      <bind name="listOfIds" value="list"/>
      <bind name="fieldName" value="'JOB_DEF_CONFIGURATION_'"/>
      <include refid="org.camunda.bpm.engine.impl.persistence.entity.Commons.applyInForPaginatedCollection"/>
  </delete>

  <sql id="andWhereMinuteInDateBetweenSql">
    <if test="parameter.minuteFrom != null and parameter.minuteTo != null">
      AND ${datepart1}<include refid="org.camunda.bpm.engine.impl.persistence.entity.Commons.periodUnitFunction"/>${datepart2}${date}${datepart3}
      between #{parameter.minuteFrom, jdbcType=INTEGER} and #{parameter.minuteTo, jdbcType=INTEGER}
    </if>
  </sql>

  <sql id="andWhereMinuteInDateBetweenSql_oracle">
    <if test="parameter.minuteFrom != null and parameter.minuteTo != null">
      AND ${datepart1}${date}${datepart2}<include refid="org.camunda.bpm.engine.impl.persistence.entity.Commons.periodUnitFunction"/>${datepart3}
      between #{parameter.minuteFrom, jdbcType=INTEGER} and #{parameter.minuteTo, jdbcType=INTEGER}
    </if>
  </sql>

  <delete id="deleteJobLogByRemovalTime"
          parameterType="org.camunda.bpm.engine.impl.db.ListQueryParameterObject">
    <bind name="date" value="'REMOVAL_TIME_'"/>
    <bind name="reportPeriodUnitName" value="'MINUTE'"/>
    delete ${limitBeforeWithoutOffset} from ${prefix}ACT_HI_JOB_LOG
    where REMOVAL_TIME_ &lt;= #{parameter.removalTime}
    <include refid="andWhereMinuteInDateBetweenSql"/>
    ${limitAfterWithoutOffset}
  </delete>

  <delete id="deleteJobLogByRemovalTime_oracle"
          parameterType="org.camunda.bpm.engine.impl.db.ListQueryParameterObject">
    <bind name="date" value="'REMOVAL_TIME_'"/>
    <bind name="reportPeriodUnitName" value="'MINUTE'"/>
    delete ${limitBeforeWithoutOffset} from ${prefix}ACT_HI_JOB_LOG
    where REMOVAL_TIME_ &lt;= #{parameter.removalTime}
    <include refid="andWhereMinuteInDateBetweenSql_oracle"/>
    ${limitAfterWithoutOffset}
  </delete>

  <delete id="deleteJobLogByRemovalTime_postgres_or_db2"
          parameterType="org.camunda.bpm.engine.impl.db.ListQueryParameterObject">
    <bind name="date" value="'REMOVAL_TIME_'"/>
    <bind name="reportPeriodUnitName" value="'MINUTE'"/>
    delete ${limitBeforeWithoutOffset} from ${prefix}ACT_HI_JOB_LOG
    where ID_ IN
      (SELECT ID_
       FROM ${prefix}ACT_HI_JOB_LOG
       WHERE REMOVAL_TIME_ &lt;= #{parameter.removalTime} <include refid="andWhereMinuteInDateBetweenSql"/>
       ${limitAfterWithoutOffset})
  </delete>

  <!-- BYTE ARRAY DELETE -->

  <delete id="deleteExceptionByteArraysByIds">
    delete
    from ${prefix}ACT_GE_BYTEARRAY
    <where>
      ID_ in (
        select J.JOB_EXCEPTION_STACK_ID_
        from ${prefix}ACT_HI_JOB_LOG J
        <where><include refid="selectExceptionByteArrayIds"/></where>
      )
    </where>
  </delete>

  <delete id="deleteExceptionByteArraysByIds_mysql">
    delete B
    from
      ${prefix}ACT_GE_BYTEARRAY B
    inner join ${prefix}ACT_HI_JOB_LOG J
      on B.ID_ = J.JOB_EXCEPTION_STACK_ID_
    <include refid="selectExceptionByteArrayIds"/>
  </delete>

  <!-- RESULT MAP -->

  <resultMap id="historicJobLogMap" type="org.camunda.bpm.engine.impl.persistence.entity.HistoricJobLogEventEntity">
    <id property="id" column="ID_" jdbcType="VARCHAR" />
    <result property="timestamp" column="TIMESTAMP_" jdbcType="TIMESTAMP" />
    <result property="jobId" column="JOB_ID_" jdbcType="VARCHAR" />
    <result property="jobDueDate" column="JOB_DUEDATE_" jdbcType="TIMESTAMP" />
    <result property="jobRetries" column="JOB_RETRIES_" jdbcType="INTEGER" />
    <result property="jobPriority" column="JOB_PRIORITY_" jdbcType="BIGINT" />
    <result property="jobExceptionMessage" column="JOB_EXCEPTION_MSG_" jdbcType="VARCHAR" />
    <result property="exceptionByteArrayId" column="JOB_EXCEPTION_STACK_ID_" jdbcType="VARCHAR" />
    <result property="jobDefinitionId" column="JOB_DEF_ID_" jdbcType="VARCHAR" />
    <result property="jobDefinitionType" column="JOB_DEF_TYPE_" jdbcType="VARCHAR" />
    <result property="jobDefinitionConfiguration" column="JOB_DEF_CONFIGURATION_" jdbcType="VARCHAR" />
    <result property="activityId" column="ACT_ID_" jdbcType="VARCHAR" />
    <result property="failedActivityId" column="FAILED_ACT_ID_" jdbcType="VARCHAR" />
    <result property="executionId" column="EXECUTION_ID_" jdbcType="VARCHAR" />
    <result property="rootProcessInstanceId" column="ROOT_PROC_INST_ID_" jdbcType="VARCHAR" />
    <result property="processInstanceId" column="PROCESS_INSTANCE_ID_" jdbcType="VARCHAR" />
    <result property="processDefinitionId" column="PROCESS_DEF_ID_" jdbcType="VARCHAR" />
    <result property="processDefinitionKey" column="PROCESS_DEF_KEY_" jdbcType="VARCHAR" />
    <result property="deploymentId" column="DEPLOYMENT_ID_" jdbcType="VARCHAR" />
    <result property="state" column="JOB_STATE_" jdbcType="INTEGER" />
    <result property="tenantId" column="TENANT_ID_" jdbcType="VARCHAR" />
    <result property="hostname" column="HOSTNAME_" jdbcType="VARCHAR" />
    <result property="sequenceCounter" column="SEQUENCE_COUNTER_" jdbcType="BIGINT" />
    <result property="removalTime" column="REMOVAL_TIME_" jdbcType="TIMESTAMP"/>
  </resultMap>

  <sql id="selectExceptionByteArrayIds">
    and J.JOB_EXCEPTION_STACK_ID_ is not null
    <if test="id != null">
      and J.ID_ = #{id, jdbcType=VARCHAR}
    </if>
    <if test="jobId != null">
      and J.JOB_ID_ = #{jobId, jdbcType=VARCHAR}
    </if>
    <if test="jobDefinitionId != null">
      and J.JOB_DEF_ID_ = #{jobDefinitionId, jdbcType=VARCHAR}
    </if>
    <if test="executionId != null">
      and J.EXECUTION_ID_ = #{executionId, jdbcType=VARCHAR}
    </if>
    <if test="processInstanceId != null">
      and J.PROCESS_INSTANCE_ID_ = #{processInstanceId, jdbcType=VARCHAR}
    </if>
    <if test="processInstanceIdIn != null &amp;&amp; processInstanceIdIn.length > 0">
      and
        <bind name="listOfIds" value="processInstanceIdIn"/>
        <bind name="fieldName" value="'J.PROCESS_INSTANCE_ID_'"/>
        <include refid="org.camunda.bpm.engine.impl.persistence.entity.Commons.applyInForPaginatedArray"/>
    </if>
    <if test="processDefinitionId != null">
      and J.PROCESS_DEF_ID_ = #{processDefinitionId, jdbcType=VARCHAR}
    </if>
    <if test="processDefinitionKey != null">
      and J.PROCESS_DEF_KEY_ = #{processDefinitionKey, jdbcType=VARCHAR}
    </if>
    <if test="deploymentId != null">
      and J.DEPLOYMENT_ID_ = #{deploymentId, jdbcType=VARCHAR}
    </if>
    <if test="jobDefinitionType != null">
      and J.JOB_DEF_TYPE_ = #{jobDefinitionType, jdbcType=VARCHAR}
    </if>
    <if test="historicBatchIdIn != null &amp;&amp; historicBatchIdIn.size > 0">
      and
        <bind name="listOfIds" value="historicBatchIdIn"/>
        <bind name="fieldName" value="'J.JOB_DEF_CONFIGURATION_'"/>
        <include refid="org.camunda.bpm.engine.impl.persistence.entity.Commons.applyInForPaginatedCollection"/>
    </if>
  </sql>

  <!-- SELECT -->

  <select id="selectHistoricJobLog" resultMap="historicJobLogMap">
    select * from ${prefix}ACT_HI_JOB_LOG where ID_ = #{id}
  </select>

  <select id="selectHistoricJobLogByQueryCriteria" parameterType="org.camunda.bpm.engine.impl.HistoricJobLogQueryImpl" resultMap="historicJobLogMap">
    <include refid="org.camunda.bpm.engine.impl.persistence.entity.Commons.bindOrderBy"/>
    ${limitBefore}
    select ${distinct} RES.*
    ${limitBetween}
    <include refid="selectHistoricJobLogByQueryCriteriaSql"/>
    ${orderBy}
    ${limitAfter}
  </select>

  <select id="selectHistoricJobLogCountByQueryCriteria" parameterType="org.camunda.bpm.engine.impl.HistoricJobLogQueryImpl" resultType="long">
    ${countDistinctBeforeStart} RES.ID_ ${countDistinctBeforeEnd}
    <include refid="selectHistoricJobLogByQueryCriteriaSql"/>
    ${countDistinctAfterEnd}
  </select>

  <sql id="selectHistoricJobLogByQueryCriteriaSql">
    from ${prefix}ACT_HI_JOB_LOG RES

    <if test="authCheck.shouldPerformAuthorizatioCheck &amp;&amp; !authCheck.revokeAuthorizationCheckEnabled &amp;&amp; authCheck.authUserId != null">
      <include refid="org.camunda.bpm.engine.impl.persistence.entity.AuthorizationEntity.authCheckJoinWithoutOnClause"/>
      AUTH ON (AUTH.RESOURCE_ID_ ${authJoinStart}
        RES.PROCESS_DEF_KEY_ ${authJoinSeparator} '*'
        <if test="authCheck.isHistoricInstancePermissionsEnabled">
          ${authJoinSeparator} RES.PROCESS_INSTANCE_ID_
        </if>
        ${authJoinEnd}
      )
    </if>

    <where>
      <if test="id != null">
        RES.ID_ = #{id}
      </if>
      <if test="jobId != null">
        and RES.JOB_ID_ = #{jobId}
      </if>
      <if test="jobExceptionMessage != null">
        and RES.JOB_EXCEPTION_MSG_ = #{jobExceptionMessage}
      </if>
      <if test="failedActivityIds != null &amp;&amp; failedActivityIds.length > 0">
        and RES.FAILED_ACT_ID_ in
        <foreach item="item" index="index" collection="failedActivityIds"
                 open="(" separator="," close=")">
          #{item}
        </foreach>
      </if>
      <if test="jobDefinitionId != null">
        and RES.JOB_DEF_ID_ = #{jobDefinitionId}
      </if>
      <if test="jobDefinitionType">
        and RES.JOB_DEF_TYPE_ = #{jobDefinitionType}
      </if>
      <if test="jobDefinitionConfiguration">
        and RES.JOB_DEF_CONFIGURATION_ = #{jobDefinitionConfiguration}
      </if>
      <if test="activityIds != null &amp;&amp; activityIds.length > 0">
        and RES.ACT_ID_ in
        <foreach item="item" index="index" collection="activityIds"
                 open="(" separator="," close=")">
          #{item}
        </foreach>
      </if>
      <if test="executionIds != null &amp;&amp; executionIds.length > 0">
        and RES.EXECUTION_ID_ in
        <foreach item="item" index="index" collection="executionIds"
                 open="(" separator="," close=")">
          #{item}
        </foreach>
      </if>
      <if test="processInstanceId != null">
        and RES.PROCESS_INSTANCE_ID_ = #{processInstanceId}
      </if>
      <if test="processDefinitionId != null">
        and RES.PROCESS_DEF_ID_ = #{processDefinitionId}
      </if>
      <if test="processDefinitionKey != null">
        and RES.PROCESS_DEF_KEY_ = #{processDefinitionKey}
      </if>
      <if test="deploymentId != null">
        and RES.DEPLOYMENT_ID_ = #{deploymentId}
      </if>
      <if test="state != null">
        and RES.JOB_STATE_ = #{state.stateCode}
      </if>
      <if test="jobPriorityHigherThanOrEqual != null">
        and RES.JOB_PRIORITY_ &gt;= #{jobPriorityHigherThanOrEqual}
      </if>
      <if test="jobPriorityLowerThanOrEqual != null">
        and RES.JOB_PRIORITY_ &lt;= #{jobPriorityLowerThanOrEqual}
      </if>
      <if test="isTenantIdSet">
        <if test="tenantIds != null &amp;&amp; tenantIds.length > 0">
          and RES.TENANT_ID_ in
          <foreach item="tenantId" index="index" collection="tenantIds"
                   open="(" separator="," close=")">
            #{tenantId}
          </foreach>
        </if>
        <if test="tenantIds == null">
          and RES.TENANT_ID_ is null
        </if>
      </if>
      <if test="hostname != null">
        and RES.HOSTNAME_ = #{hostname, jdbcType=VARCHAR}
      </if>

      <if test="authCheck.shouldPerformAuthorizatioCheck &amp;&amp; authCheck.authUserId != null">
        <!-- incident exists in context of a process definition -->
        and (
          (RES.PROCESS_DEF_KEY_ is not null
          <include refid="org.camunda.bpm.engine.impl.persistence.entity.AuthorizationEntity.queryAuthorizationCheck"/>
          ) or RES.PROCESS_DEF_KEY_ is null
        )
      </if>

      <include refid="org.camunda.bpm.engine.impl.persistence.entity.TenantEntity.queryTenantCheck" />

    </where>
  </sql>

</mapper>
